/*
 * Copyright (C) 2009 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.trackedbean.binding.guicomponents.action;

import java.util.*;
import javax.swing.*;

/**
 * Extended Popup Helper dealing with local actions.
 * 
 * @author M. Hautle
 */
public class LocalPopupManager extends PopupHelper {
	/** The local action. */
	protected final List<ActionEntry> localActions = new ArrayList<ActionEntry>();

	/**
	 * Flag indicating if the popup should be populated using {@link ActionManager#initPopup(List, PopupHelper)} and the appending the {@link #localActions}
	 * (true) or just by appending the {@link #localActions} (false).
	 */
	protected boolean global = true;

	/**
	 * Populates the given menu with the local actions and appends the one registred by the {@link ActionManager} if {@link #global} is set.
	 * 
	 * @param <T> The selection type
	 * 
	 * @param menu The menu to populate
	 * @param selection The selection for which the menu gets populated
	 * @return The populated menu
	 */
	public <T> JPopupMenu populate(JPopupMenu menu, List<T> selection) {
		return populate(menu, selection, global);
	}

	/**
	 * Populates the given menu with the actions registred in the {@link ActionManager} and adds the local actions.
	 * 
	 * @param <T> The selection type
	 * 
	 * @param menu The menu to populate
	 * @param selection The selection for which the menu gets populated
	 * @param global Flag indicating if the popup should be populated using {@link ActionManager#initPopup(List, PopupHelper)} and the appending the
	 *            {@link #localActions} (true) or just by appending the {@link #localActions} (false)
	 * @return The populated menu
	 */
	public <T> JPopupMenu populate(JPopupMenu menu, List<T> selection, boolean global) {
		prepareAndSetPopup(menu);
		if (global)
			ActionManager.ME.initPopup(selection, this);
		for (ActionEntry<T> e : localActions)
			e.addAction(selection, this);
		removeEndSeperators();
		cleanUp();
		return menu;
	}

	/**
	 * Adds a local action.
	 * 
	 * @param <T> The selection type
	 * 
	 * @param path The location where to add the action
	 * @param action The action
	 */
	public <T> void addLocalAction(String path, ISelectionAction<T> action) {
		localActions.add(new ActionEntry<T>(action, path));
	}

	/**
	 * Adds a local action.
	 * 
	 * @param <T> The selection type
	 * 
	 * @param action The action
	 */
	public <T> void addLocalAction(ISelectionAction<T> action) {
		addLocalAction("", action);
	}

	/**
	 * Removes the given local action.
	 * 
	 * @param action The action to remove
	 * @return True if the action was removed
	 */
	public boolean removeLocalAction(ISelectionAction action) {
		for (int i = 0, cnt = localActions.size(); i < cnt; i++) {
			if (!localActions.get(i).holds(action))
				continue;
			localActions.remove(i);
			return true;
		}
		return false;
	}

	/**
	 * See {@link #global}.
	 * 
	 * @return Returns the global flag.
	 */
	public boolean isGlobal() {
		return global;
	}

	/**
	 * This settings affects the behaviour of {@link #populate(JPopupMenu, List)}. See {@link #global}.<br>
	 * 
	 * @param global True if local and {@link ActionManager} actions should be added, false if only the local ones should be added
	 */
	public void setGlobal(boolean global) {
		this.global = global;
	}

	/**
	 * Entry holding an action and it's location.
	 * 
	 * @param <T> The selection type of the action
	 * 
	 * @author M. Hautle
	 */
	protected static class ActionEntry<T> {
		/** The action. */
		protected final ISelectionAction<T> action;

		/** The location where to add the action. */
		protected final String location;

		/**
		 * Default constructor.
		 * 
		 * @param action The action
		 * @param location The location of the action in the popupmenu
		 */
		protected ActionEntry(ISelectionAction<T> action, String location) {
			this.action = action;
			this.location = location;
		}

		/**
		 * Checks wherever this entry holds the given action.
		 * 
		 * @param a The action to check
		 * @return True if this entry holds the given action
		 */
		protected boolean holds(ISelectionAction a) {
			return action == a;
		}

		/**
		 * Adds the action using the given popuphelper if it's active for the given selection.
		 * 
		 * @param selection The selection
		 * @param helper The popup helper
		 */
		protected void addAction(List<T> selection, PopupHelper helper) {
			if (action.selectionChanged(selection))
				helper.addAction(location, action);
		}
	}
}
